home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / ATMOSPH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  48.6 KB  |  2,500 lines

  1. /****************************************************************************
  2. *                   atmosph.c
  3. *
  4. *  This module contains all functions for atmospheric effects.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "atmosph.h"
  28. #include "colour.h"
  29. #include "povray.h"
  30. #include "texture.h"
  31. #include "pigment.h"
  32. #include "objects.h"
  33. #include "lighting.h"
  34. #include "matrices.h"
  35. #include "texture.h"
  36.  
  37.  
  38.  
  39. /*****************************************************************************
  40. * Local preprocessor defines
  41. ******************************************************************************/
  42.  
  43. #define BLACK_LEVEL 0.0001
  44.  
  45.  
  46.  
  47. /*****************************************************************************
  48. * Local typedefs
  49. ******************************************************************************/
  50.  
  51. typedef struct Light_List_Struct LIGHT_LIST;
  52.  
  53. struct Light_List_Struct
  54. {
  55.   int active;
  56.   DBL t1, t2;
  57.   LIGHT_SOURCE *Light;
  58. };
  59.  
  60.  
  61.  
  62. /*****************************************************************************
  63. * Local variables
  64. ******************************************************************************/
  65.  
  66. /*
  67.  * Atmosphere stuff.
  68.  */
  69.  
  70. /* List of active lights. */
  71.  
  72. static LIGHT_LIST *Light_List;
  73.  
  74. /* Min. and max. intersetcion depths with light source areas. */
  75.  
  76. static DBL *tmin, *tmax;
  77.  
  78.  
  79.  
  80. /*****************************************************************************
  81. * Static functions
  82. ******************************************************************************/
  83.  
  84. static DBL constant_fog PARAMS((RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour));
  85. static DBL ground_fog PARAMS((RAY *Ray, DBL Depth, DBL Width, FOG *Fog, COLOUR Colour));
  86.  
  87. static void supersample_atmosphere PARAMS((LIGHT_LIST *Light_List,
  88.   int level, RAY *Ray, ATMOSPHERE *Atmosphere,
  89.   DBL d1, COLOUR C1, DBL d3, COLOUR C3));
  90.  
  91. static void sample_atmosphere PARAMS((LIGHT_LIST *Light_List, DBL dist,
  92.   RAY *Ray, ATMOSPHERE *Atmosphere, COLOUR Col));
  93.  
  94. static int intersect_spotlight PARAMS((RAY *Ray, LIGHT_SOURCE *Light, DBL *d1, DBL *d2));
  95. static int intersect_cylinderlight PARAMS((RAY *Ray, LIGHT_SOURCE *Light, DBL *d1, DBL *d2));
  96.  
  97. static void do_atmospheric_scattering PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour, int Light_Ray_Flag));
  98. static void do_fog PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour, int Light_Ray_Flag));
  99. static void do_rainbow PARAMS((RAY *Ray, INTERSECTION *Intersection, COLOUR Colour));
  100. static void do_skysphere PARAMS((RAY *Ray, COLOUR Colour));
  101.  
  102.  
  103.  
  104. /*****************************************************************************
  105. *
  106. * FUNCTION
  107. *
  108. *   Initialize_Atmosphere_Code
  109. *
  110. * INPUT
  111. *
  112. * OUTPUT
  113. *
  114. * RETURNS
  115. *
  116. * AUTHOR
  117. *
  118. *   Dieter Bayer
  119. *
  120. * DESCRIPTION
  121. *
  122. *   Initialize atmosphere specific variables.
  123. *
  124. * CHANGES
  125. *
  126. *   Aug 1995 : Creation.
  127. *
  128. ******************************************************************************/
  129.  
  130. void Initialize_Atmosphere_Code()
  131. {
  132.   Light_List = NULL;
  133.  
  134.   tmin = NULL;
  135.   tmax = NULL;
  136.  
  137.   /* Allocate memory for atmosphere. */
  138.  
  139.   if ((Frame.Atmosphere != NULL) && 
  140.       (fabs(Frame.Atmosphere->Distance) > EPSILON) &&
  141.       (Frame.Number_Of_Light_Sources > 0))
  142.   {
  143.     Light_List = (LIGHT_LIST *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(LIGHT_LIST), "atmosphere sampling lists");
  144.  
  145.     tmin = (DBL *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(DBL), "atmosphere sampling lists");
  146.  
  147.     tmax = (DBL *)POV_MALLOC(Frame.Number_Of_Light_Sources * sizeof(DBL), "atmosphere sampling lists");
  148.   }
  149. }
  150.  
  151.  
  152.  
  153. /*****************************************************************************
  154. *
  155. * FUNCTION
  156. *
  157. *   Deinitialize_Atmosphere_Code
  158. *
  159. * INPUT
  160. *
  161. * OUTPUT
  162. *
  163. * RETURNS
  164. *
  165. * AUTHOR
  166. *
  167. *   Dieter Bayer
  168. *
  169. * DESCRIPTION
  170. *
  171. *   Deinitialize atmosphere specific variables.
  172. *
  173. * CHANGES
  174. *
  175. *   Aug 1995 : Creation.
  176. *
  177. ******************************************************************************/
  178.  
  179. void Deinitialize_Atmosphere_Code()
  180. {
  181.   /* Free memory used by atmosphere. */
  182.  
  183.   if (Light_List != NULL)
  184.   {
  185.     POV_FREE(Light_List);
  186.     POV_FREE(tmin);
  187.     POV_FREE(tmax);
  188.   }
  189.  
  190.   Light_List = NULL;
  191.  
  192.   tmin = NULL;
  193.   tmax = NULL;
  194. }
  195.  
  196.  
  197.  
  198. /*****************************************************************************
  199. *
  200. * FUNCTION
  201. *
  202. *   Do_Infinite_Atmosphere
  203. *
  204. * INPUT
  205. *
  206. *   Ray    - Current ray
  207. *
  208. * OUTPUT
  209. *
  210. *   Colour - Color of the current ray
  211. *
  212. * RETURNS
  213. *   
  214. * AUTHOR
  215. *
  216. *   Dieter Bayer
  217. *   
  218. * DESCRIPTION
  219. *
  220. *   Apply atmospheric effects to an infinite ray.
  221. *
  222. * CHANGES
  223. *
  224. *   Feb 1995 : Creation.
  225. *
  226. *   Jun 1995 : Added code for alpha channel support. [DB]
  227. *
  228. ******************************************************************************/
  229.  
  230. void Do_Infinite_Atmosphere(Ray, Colour)
  231. RAY *Ray;
  232. COLOUR Colour;
  233. {
  234.   /* Set background color. */
  235.  
  236.   Assign_Colour(Colour, Frame.Background_Colour);
  237.   
  238.   Colour[FILTER] = 0.0;
  239.   Colour[TRANSM] = 1.0;
  240.  
  241.   /* Determine atmospheric effects for infinite ray. */
  242.  
  243.   do_skysphere(Ray, Colour);
  244. }
  245.  
  246.  
  247.  
  248. /*****************************************************************************
  249. *
  250. * FUNCTION
  251. *
  252. *   Do_Finite_Atmosphere
  253. *
  254. * INPUT
  255. *
  256. *   Ray            - Current ray
  257. *   Intersection   - Current intersection
  258. *   Light_Ray_Flag - TRUE if ray is a light source ray
  259. *
  260. * OUTPUT
  261. *
  262. *   Colour         - Color of the current ray
  263. *
  264. * RETURNS
  265. *
  266. * AUTHOR
  267. *
  268. *   Dieter Bayer
  269. *
  270. * DESCRIPTION
  271. *
  272. *   Apply atmospheric effects to a finite ray.
  273. *
  274. * CHANGES
  275. *
  276. *   Feb 1995 : Creation.
  277. *
  278. ******************************************************************************/
  279.  
  280. void Do_Finite_Atmosphere(Ray, Intersection, Colour, Light_Ray_Flag)
  281. RAY *Ray;
  282. INTERSECTION *Intersection;
  283. COLOUR Colour;
  284. int Light_Ray_Flag;
  285. {
  286.   if (!Light_Ray_Flag)
  287.   {
  288.     do_rainbow(Ray, Intersection, Colour);
  289.   }
  290.  
  291.   do_atmospheric_scattering(Ray, Intersection, Colour, Light_Ray_Flag);
  292.  
  293.   do_fog(Ray, Intersection, Colour, Light_Ray_Flag);
  294. }
  295.  
  296.  
  297.  
  298. /*****************************************************************************
  299. *
  300. * FUNCTION
  301. *
  302. *   do_atmospheric_scattering
  303. *
  304. * INPUT
  305. *
  306. *   Ray            - Current ray
  307. *   Intersection   - Current intersection
  308. *   Light_Ray_Flag - TRUE if ray is a light source ray
  309. *
  310. * OUTPUT
  311. *
  312. *   Colour         - Color of the current ray
  313. *
  314. * RETURNS
  315. *
  316. * AUTHOR
  317. *
  318. *   Dieter Bayer
  319. *
  320. * DESCRIPTION
  321. *
  322. *   Simulate atmospheric scattering using volume sampling.
  323. *
  324. *   Ideas for the atmospheric scattering were taken from:
  325. *
  326. *     - M. Inakage, "An Illumination Model for Atmospheric Environments", ..
  327. *
  328. *     - Nishita, T., Miyawaki, Y. and Nakamae, E., "A Shading Model for
  329. *       Atmospheric Scattering Considering Luminous Intensity Distribution
  330. *       of Light Sources", Computer Graphics, 21, 4, 1987, 303-310
  331. *
  332. * CHANGES
  333. *
  334. *   Nov 1994 : Creation.
  335. *
  336. *   Jan 1995 : Added support of cylindrical light sources. [DB]
  337. *
  338. *   Jun 1995 : Added code for alpha channel support. [DB]
  339. *
  340. ******************************************************************************/
  341.  
  342. static void do_atmospheric_scattering(Ray, Intersection, Colour, Light_Ray_Flag)
  343. RAY *Ray;
  344. INTERSECTION *Intersection;
  345. COLOUR Colour;
  346. int Light_Ray_Flag;
  347. {
  348.   int i, j;
  349.   int active, interval, intervals, insert;
  350.   DBL k, jdist, t1, t2, f, fi;
  351.   DBL dist, dist_prev;
  352.   DBL step;
  353.   COLOUR Col_total, Col, Col_prev, Max_Colour, C1, C2;
  354.   LIGHT_SOURCE *Light;
  355.   ATMOSPHERE *Atmosphere;
  356.  
  357.   /* Why are we here? */
  358.  
  359.   if (((Atmosphere = Frame.Atmosphere) == NULL) || 
  360.       (Frame.Atmosphere->Distance == 0.0) ||
  361.       (Frame.Number_Of_Light_Sources == 0))
  362.   {
  363.     return;
  364.   }
  365.  
  366.   /*
  367.    * If we have a light source ray we only have to attenuate
  368.    * the light source color due to the distance traveled.
  369.    */
  370.  
  371.   if (Light_Ray_Flag)
  372.   {
  373.     k = exp(-Intersection->Depth / Atmosphere->Distance);
  374.  
  375.     /* Check for minimum transmittance. */
  376.  
  377.     if (k < Atmosphere->Colour[TRANSM])
  378.     {
  379.       k = Atmosphere->Colour[TRANSM];
  380.     }
  381.  
  382.     VScaleEq(Colour, k);
  383.  
  384.     return;
  385.   }
  386.  
  387.   /* Init light list and sampling intervals. */
  388.  
  389.   for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  390.   {
  391.     Light_List[i].active = FALSE;
  392.     Light_List[i].t1     = 0.0;
  393.     Light_List[i].t2     = Max_Distance;
  394.     Light_List[i].Light  = NULL;
  395.  
  396.     tmin[i] =  BOUND_HUGE;
  397.     tmax[i] = -BOUND_HUGE;
  398.   }
  399.  
  400.   /* Get depths for all light sources and disconnected sampling intervals. */
  401.  
  402.   active = 0;
  403.  
  404.   intervals = 0;
  405.  
  406.   t1 = t2 = 0.0;
  407.  
  408.   Make_Colour(Max_Colour, 0.0, 0.0, 0.0);
  409.  
  410.   for (i = 0, Light = Frame.Light_Sources; Light != NULL; Light = Light->Next_Light_Source, i++)
  411.   {
  412.     insert = FALSE;
  413.  
  414.     Light_List[i].Light = Light;
  415.  
  416.     if (!Light->Atmosphere_Interaction)
  417.     {
  418.       continue;
  419.     }
  420.  
  421.     switch (Light->Light_Type)
  422.     {
  423.       case CYLINDER_SOURCE:
  424.  
  425.         if (intersect_cylinderlight(Ray, Light, &t1, &t2))
  426.         {
  427.           if ((t1 < Intersection->Depth) && (t2 > Small_Tolerance))
  428.           {
  429.             insert = TRUE;
  430.           }
  431.         }
  432.  
  433.         break;
  434.  
  435.       case POINT_SOURCE:
  436.  
  437.         t1 = 0.0;
  438.         t2 = Intersection->Depth;
  439.  
  440.         insert = TRUE;
  441.  
  442.         break;
  443.  
  444.       case SPOT_SOURCE:
  445.  
  446.         if (intersect_spotlight(Ray, Light, &t1, &t2))
  447.         {
  448.           if ((t1 < Intersection->Depth) && (t2 > Small_Tolerance))
  449.           {
  450.             insert = TRUE;
  451.           }
  452.         }
  453.  
  454.         break;
  455.     }
  456.  
  457.     /* Insert distances into sampling interval list. */
  458.  
  459.     if (insert)
  460.     {
  461.       /* Add light color to maximum color. */
  462.  
  463.       VAddEq(Max_Colour, Light->Colour);
  464.  
  465.       /* Number of active light sources. */
  466.  
  467.       active ++;
  468.  
  469.       /* Insert light source intersections into light list. */
  470.  
  471.       t1 = max(t1, 0.0);
  472.       t2 = min(t2, Intersection->Depth);
  473.  
  474.       Light_List[i].active = TRUE;
  475.       Light_List[i].t1 = t1;
  476.       Light_List[i].t2 = t2;
  477.  
  478.       /* Test if there's an overlapping interval. */
  479.  
  480.       for (j = 0; j < intervals; j++)
  481.       {
  482.         if (!((t2 < tmin[j]) || (t1 > tmax[j])))
  483.         {
  484.           /* The intervals are overlapping. */
  485.  
  486.           break;
  487.         }
  488.       }
  489.  
  490.       if (j >= intervals)
  491.       {
  492.         j = intervals;
  493.  
  494.         intervals++;
  495.       }
  496.  
  497.       /* Adjust interval. */
  498.  
  499.       tmin[j] = min(tmin[j], t1);
  500.       tmax[j] = max(tmax[j], t2);
  501.     }
  502.   }
  503.  
  504.   /* Initialize maximum color. */
  505.  
  506.   Max_Colour[RED]   = (Max_Colour[RED]   > EPSILON) ? 1.0 : 0.0;
  507.   Max_Colour[GREEN] = (Max_Colour[GREEN] > EPSILON) ? 1.0 : 0.0;
  508.   Max_Colour[BLUE]  = (Max_Colour[BLUE]  > EPSILON) ? 1.0 : 0.0;
  509.  
  510.   /*
  511.    * If there are no active lights, we can skip ahead because no
  512.    * light from any light source will reach the viewer.
  513.    */
  514.  
  515.   Make_Colour(Col_total, 0.0, 0.0, 0.0);
  516.  
  517.   if (active > 0)
  518.   {
  519.     for (interval = 0; interval < intervals; interval++)
  520.     {
  521.       /* Get sampling step distance. */
  522.  
  523.       step = min((tmax[interval] - tmin[interval]), Atmosphere->Distance) / (DBL)Atmosphere->Samples;
  524.  
  525.       /* Set up distance. */
  526.  
  527.       dist = dist_prev = 0.0;
  528.  
  529.       /* Sample along the ray. */
  530.  
  531.       Make_Colour(Col, 0.0, 0.0, 0.0);
  532.  
  533.       for (i = 0; dist < tmax[interval]; i++)
  534.       {
  535.         /* Step to next sample point. */
  536.  
  537.         dist = tmin[interval] + ((DBL)i + 0.5) * step;
  538.  
  539.         /* Get distance of current sampling point. */
  540.  
  541.         jdist = dist + Atmosphere->Jitter * step * (FRAND() - 0.5);
  542.  
  543.         /* If we're behind the intersection point we can quit. */
  544.  
  545.         if (jdist >= Intersection->Depth)
  546.         {
  547.           break;
  548.         }
  549.  
  550.         sample_atmosphere(Light_List, jdist, Ray, Atmosphere, Col);
  551.  
  552.         /* Add previous result to the total color. */
  553.  
  554.         if (i)
  555.         {
  556.           /* Do the current and previous colours differ too much? */
  557.  
  558.           if ((Atmosphere->AA_Level > 0) && (Colour_Distance(Col, Col_prev) >= Atmosphere->AA_Threshold))
  559.           {
  560.             /* Supersample between current and previous point. */
  561.  
  562.             supersample_atmosphere(Light_List, 1, Ray, Atmosphere, dist_prev, Col_prev, dist, Col);
  563.  
  564.             Col[RED]   = Col_prev[RED]   = 0.5 * (Col[RED]   + Col_prev[RED]);
  565.             Col[GREEN] = Col_prev[GREEN] = 0.5 * (Col[GREEN] + Col_prev[GREEN]);
  566.             Col[BLUE]  = Col_prev[BLUE]  = 0.5 * (Col[BLUE]  + Col_prev[BLUE]);
  567.           }
  568.  
  569.           /* Get attenuation due to distance from view point. */
  570.  
  571.           k = step * exp(-dist_prev / Atmosphere->Distance);
  572.  
  573.           /* If the contribution is too small we can stop. */
  574.  
  575.           if (k < BLACK_LEVEL)
  576.           {
  577.             break;
  578.           }
  579.  
  580.           Col_total[RED]   += k * Col_prev[RED];
  581.           Col_total[GREEN] += k * Col_prev[GREEN];
  582.           Col_total[BLUE]  += k * Col_prev[BLUE];
  583.  
  584.           /* If the total color is larger than max. value we can stop now. */
  585.  
  586.           if ((Col_total[RED]   >= Max_Colour[RED])   &&
  587.               (Col_total[GREEN] >= Max_Colour[GREEN]) &&
  588.               (Col_total[BLUE]  >= Max_Colour[BLUE]))
  589.           {
  590.             break;
  591.           }
  592.         }
  593.  
  594.         dist_prev = dist;
  595.  
  596.         Assign_Colour(Col_prev, Col);
  597.       }
  598.  
  599.       /* Add last result to the total color. */
  600.  
  601.       /* Get attenuation due to distance from view point. */
  602.  
  603.       k = step * exp(-dist / Atmosphere->Distance);
  604.  
  605.       Col_total[RED]   += k * Col_prev[RED];
  606.       Col_total[GREEN] += k * Col_prev[GREEN];
  607.       Col_total[BLUE]  += k * Col_prev[BLUE];
  608.  
  609.       /* If the total color is white already we can stop now. */
  610.  
  611.       if ((Col_total[RED] >= 1.0) && (Col_total[GREEN] >= 1.0) && (Col_total[BLUE] >= 1.0))
  612.       {
  613.         break;
  614.       }
  615.     }
  616.   }
  617.  
  618.   /* Add attenuated background color. */
  619.  
  620.   k = exp(-Intersection->Depth / Atmosphere->Distance);
  621.  
  622.   /* Check for minimum transmittance. */
  623.  
  624.   if (k < Atmosphere->Colour[TRANSM])
  625.   {
  626.     k = Atmosphere->Colour[TRANSM];
  627.   }
  628.  
  629. /*
  630.   ki = 1.0 - k;
  631.  
  632.   VLinComb3(Colour, 1.0, Col_total, k, Colour, ki, Atmosphere->Colour);
  633. */
  634.  
  635.   /* Attenuate color due to atmosphere color. */
  636.  
  637.   f = Atmosphere->Colour[FILTER];
  638.  
  639.   fi = 1.0 - f;
  640.  
  641.   C1[RED]   = Col_total[RED]   * (fi + f * Atmosphere->Colour[RED]);
  642.   C1[GREEN] = Col_total[GREEN] * (fi + f * Atmosphere->Colour[GREEN]);
  643.   C1[BLUE]  = Col_total[BLUE]  * (fi + f * Atmosphere->Colour[BLUE]);
  644.  
  645.   C2[RED]   = Colour[RED]   * (fi + f * Atmosphere->Colour[RED]);
  646.   C2[GREEN] = Colour[GREEN] * (fi + f * Atmosphere->Colour[GREEN]);
  647.   C2[BLUE]  = Colour[BLUE]  * (fi + f * Atmosphere->Colour[BLUE]);
  648.  
  649.   VLinComb2(Colour, 1.0, C1, k, C2);
  650.  
  651.   Colour[FILTER] = k * Colour[FILTER];
  652.   Colour[TRANSM] = k * Colour[TRANSM];
  653. }
  654.  
  655.  
  656.  
  657. /*****************************************************************************
  658. *
  659. * FUNCTION
  660. *
  661. *   supersample_atmosphere
  662. *
  663. * INPUT
  664. *
  665. *   Light_List   - array containing light source information
  666. *   level        - level of recursion
  667. *   Ray          - pointer to ray
  668. *   Atmosphere   - pointer to atmosphere to use
  669. *   d1           - distance to lower sample
  670. *   d3           - distance to upper sample
  671. *
  672. * OUTPUT
  673. *
  674. *   C1           - Color of lower sample
  675. *   C3           - Color of upper sample
  676. *
  677. * RETURNS
  678. *
  679. * AUTHOR
  680. *
  681. *   Dieter Bayer
  682. *
  683. * DESCRIPTION
  684. *
  685. *   Recursevily supersample between two points on the ray.
  686. *
  687. * CHANGES
  688. *
  689. *   Nov 1994 : Creation.
  690. *
  691. ******************************************************************************/
  692.  
  693. static void supersample_atmosphere(Light_List, level, Ray, Atmosphere, d1, C1, d3, C3)
  694. LIGHT_LIST *Light_List;
  695. int level;
  696. RAY *Ray;
  697. ATMOSPHERE *Atmosphere;
  698. DBL d1, d3;
  699. COLOUR C1, C3;
  700. {
  701.   DBL d2, jdist;
  702.   COLOUR C2;
  703.  
  704.   Increase_Counter(stats[Atmosphere_Supersamples]);
  705.  
  706.   /* Sample between lower and upper point. */
  707.  
  708.   d2 = 0.5 * (d1 + d3);
  709.  
  710.   jdist = d2 + Atmosphere->Jitter * 0.5 * (d3 - d1) * (FRAND() - 0.5);
  711.  
  712.   sample_atmosphere(Light_List, jdist, Ray, Atmosphere, C2);
  713.  
  714.   /* Test for further supersampling. */
  715.  
  716.   if (level < Atmosphere->AA_Level)
  717.   {
  718.     if (Colour_Distance(C1, C2) >= Atmosphere->AA_Threshold)
  719.     {
  720.       /* Supersample between lower and middle point. */
  721.  
  722.       supersample_atmosphere(Light_List, level+1, Ray, Atmosphere, d1, C1, d2, C2);
  723.     }
  724.  
  725.     if (Colour_Distance(C2, C3) >= Atmosphere->AA_Threshold)
  726.     {
  727.       /* Supersample between current and higher point. */
  728.  
  729.       supersample_atmosphere(Light_List, level+1, Ray, Atmosphere, d2, C2, d3, C3);
  730.     }
  731.   }
  732.  
  733.   /* Add supersampled colors. */
  734.  
  735.   VLinComb2(C1, 0.75, C1, 0.25, C2);
  736.   VLinComb2(C3, 0.25, C2, 0.75, C3);
  737. }
  738.  
  739.  
  740.  
  741. /*****************************************************************************
  742. *
  743. * FUNCTION
  744. *
  745. *   sample_atmosphere
  746. *
  747. * INPUT
  748. *
  749. *   Light_List   - array containing light source information
  750. *   dist         - distance of current sample
  751. *   Ray          - pointer to ray
  752. *   Atmosphere   - pointer to atmosphere to use
  753. *
  754. * OUTPUT
  755. *
  756. *   Col          - color of current sample
  757. *
  758. * RETURNS
  759. *
  760. * AUTHOR
  761. *
  762. *   Dieter Bayer
  763. *
  764. * DESCRIPTION
  765. *
  766. *   Calculate the color of the current atmosphere sample, i.e. the
  767. *   sample at distance dist, by summing the light reaching that point
  768. *   from all light sources.
  769. *
  770. * CHANGES
  771. *
  772. *   Nov 1994 : Creation.
  773. *
  774. ******************************************************************************/
  775.  
  776. static void sample_atmosphere(Light_List, dist, Ray, Atmosphere, Col)
  777. LIGHT_LIST *Light_List;
  778. DBL dist;
  779. RAY *Ray;
  780. ATMOSPHERE *Atmosphere;
  781. COLOUR Col;
  782. {
  783.   int i;
  784.   DBL alpha, len, k, g, g2;
  785.   VECTOR P;
  786.   COLOUR Light_Colour;
  787.   RAY Light_Ray;
  788.  
  789.   Increase_Counter(stats[Atmosphere_Samples]);
  790.  
  791.   /* Get current sample point. */
  792.  
  793.   VEvaluateRay(P, Ray->Initial, dist, Ray->Direction);
  794.  
  795.   /* Process all light sources. */
  796.  
  797.   Make_Colour(Col, 0.0, 0.0, 0.0);
  798.  
  799.   for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  800.   {
  801.     /* Use light only if active and within it's boundaries. */
  802.  
  803.     if (Light_List[i].active && (dist >= Light_List[i].t1) && (dist <= Light_List[i].t2))
  804.     {
  805.       if (!(Test_Shadow(Light_List[i].Light, &len, &Light_Ray, Ray, P, Light_Colour)))
  806.       {
  807.         VDot(alpha, Light_Ray.Direction, Ray->Direction);
  808.  
  809.         /* Get attenuation due to scattering. */
  810.  
  811.         switch (Atmosphere->Type)
  812.         {
  813.           case RAYLEIGH_SCATTERING:
  814.  
  815.             k = (1.0 + Sqr(alpha)) / 2.0;
  816.  
  817.             break;
  818.  
  819.           case MIE_HAZY_SCATTERING:
  820.  
  821.             k = 0.1 * (1.0 + 0.03515625 * pow(1.0 + alpha, 8.0));
  822.  
  823.             break;
  824.  
  825.           case MIE_MURKY_SCATTERING:
  826.  
  827.             k = 0.019607843 * (1.0 + 1.1641532e-8 * pow(1.0 + alpha, 32.0));
  828.  
  829.             break;
  830.  
  831.           case HENYEY_GREENSTEIN_SCATTERING:
  832.  
  833.             g = Atmosphere->Eccentricity;
  834.  
  835.             g2 = Sqr(g);
  836.  
  837.             k = (1.0 - g2) / pow(1.0 + g2 - 2.0 * g * alpha, 1.5);
  838.  
  839.             break;
  840.  
  841.           case ISOTROPIC_SCATTERING:
  842.           default:
  843.  
  844.             k = 1.0;
  845.  
  846.             break;
  847.         }
  848.  
  849.         k *= Atmosphere->Scattering;
  850.  
  851.         VAddScaledEq(Col, k, Light_Colour);
  852.       }
  853.     }
  854.   }
  855. }
  856.  
  857.  
  858.  
  859. /*****************************************************************************
  860. *
  861. * FUNCTION
  862. *
  863. *   do_fog
  864. *
  865. * INPUT
  866. *
  867. *   Ray            - current ray
  868. *   Intersection   - current intersection
  869. *   Light_Ray_Flag - TRUE if ray is a light source ray
  870. *
  871. * OUTPUT
  872. *
  873. *   Colour         - color of current ray
  874. *
  875. * RETURNS
  876. *
  877. * AUTHOR
  878. *
  879. *   POV-Ray Team
  880. *
  881. * DESCRIPTION
  882. *
  883. *   Evaluate all fogs for the current ray and intersection.
  884. *
  885. * CHANGES
  886. *
  887. *   Dec 1994 : Rewritten to allow multiple fogs. [DB]
  888. *
  889. *   Apr 1995 : Added transmittance threshold and filtering. [DB]
  890. *
  891. *   Jun 1995 : Added code for alpha channel support. [DB]
  892. *
  893. ******************************************************************************/
  894.  
  895. static void do_fog(Ray, Intersection, Colour, Light_Ray_Flag)
  896. RAY *Ray;
  897. INTERSECTION *Intersection;
  898. COLOUR Colour;
  899. int Light_Ray_Flag;
  900. {
  901.   DBL att, att_inv, width;
  902.   COLOUR Col_Fog;
  903.   COLOUR sum_att;  /* total attenuation. */
  904.   COLOUR sum_col;  /* total color.       */
  905.   FOG *Fog;
  906.  
  907.   /* Why are we here. */
  908.  
  909.   if (Frame.Fog == NULL)
  910.   {
  911.     return;
  912.   }
  913.  
  914.   /* Init total attenuation and total color. */
  915.  
  916.   Make_ColourA(sum_att, 1.0, 1.0, 1.0, 1.0, 1.0);
  917.   Make_ColourA(sum_col, 0.0, 0.0, 0.0, 0.0, 0.0);
  918.  
  919.   /* Loop over all fogs. */
  920.  
  921.   for (Fog = Frame.Fog; Fog != NULL; Fog = Fog->Next)
  922.   {
  923.     /* Don't care about fogs with zero distance. */
  924.  
  925.     if (fabs(Fog->Distance) > EPSILON)
  926.     {
  927.       width = Intersection->Depth;
  928.  
  929.       switch (Fog->Type)
  930.       {
  931.         case GROUND_MIST:
  932.  
  933.           att = ground_fog(Ray, 0.0, width, Fog, Col_Fog);
  934.  
  935.           break;
  936.  
  937.         default:
  938.  
  939.           att = constant_fog(Ray, 0.0, width, Fog, Col_Fog);
  940.  
  941.           break;
  942.       }
  943.  
  944.       /* Check for minimum transmittance. */
  945.  
  946.       if (att < Col_Fog[TRANSM])
  947.       {
  948.         att = Col_Fog[TRANSM];
  949.       }
  950.  
  951.       /* Get attenuation sum due to filtered/unfiltered translucency. */
  952.  
  953.       sum_att[RED]    *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[RED]);
  954.       sum_att[GREEN]  *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[GREEN]);
  955.       sum_att[BLUE]   *= att * ((1.0 - Col_Fog[FILTER]) + Col_Fog[FILTER] * Col_Fog[BLUE]);
  956.       sum_att[FILTER] *= att * Col_Fog[FILTER];
  957.       sum_att[TRANSM] *= att * Col_Fog[TRANSM];
  958.  
  959.       if (!Light_Ray_Flag)
  960.       {
  961.         att_inv = 1.0 - att;
  962.  
  963.         VAddScaledEq(sum_col, att_inv, Col_Fog);
  964.       }
  965.     }
  966.   }
  967.  
  968.   /* Add light coming from background. */
  969.  
  970.   sum_col[RED]    += sum_att[RED]    * Colour[RED];
  971.   sum_col[GREEN]  += sum_att[GREEN]  * Colour[GREEN];
  972.   sum_col[BLUE]   += sum_att[BLUE]   * Colour[BLUE];
  973.   sum_col[FILTER] += sum_att[FILTER] * Colour[FILTER];
  974.   sum_col[TRANSM] += sum_att[TRANSM] * Colour[TRANSM];
  975.  
  976.   Assign_Colour(Colour, sum_col);
  977. }
  978.  
  979.  
  980.  
  981. /*****************************************************************************
  982. *
  983. * FUNCTION
  984. *
  985. *   do_rainbow
  986. *
  987. * INPUT
  988. *
  989. *   Ray          - Current ray
  990. *   Intersection - Cuurent intersection
  991. *
  992. * OUTPUT
  993. *
  994. *   Colour       - Current colour
  995. *
  996. * RETURNS
  997. *
  998. * AUTHOR
  999. *
  1000. *   Dieter Bayer
  1001. *
  1002. * DESCRIPTION
  1003. *
  1004. *   Create a rainbow using an impressionistic model.
  1005. *
  1006. *   The model was taken from:
  1007. *
  1008. *     Musgrave, F. Kenton, "Prisms and Rainbows: a Dispersion Model
  1009. *     for Computer Graphics", Proceedings of Graphics Interface '89 -
  1010. *     Vision Interface '89, p. 227-234.
  1011. *
  1012. * CHANGES
  1013. *
  1014. *   Jul 1994 : Creation.
  1015. *
  1016. *   Dec 1994 : Modified to allow multiple rainbows. [DB]
  1017. *
  1018. *   Apr 1995 : Added rainbow arcs and filtering. [DB]
  1019. *
  1020. *   Jun 1995 : Added code for alpha channel support. [DB]
  1021. *
  1022. ******************************************************************************/
  1023.  
  1024. static void do_rainbow(Ray, Intersection, Colour)
  1025. RAY *Ray;
  1026. INTERSECTION *Intersection;
  1027. COLOUR Colour;
  1028. {
  1029.   int n;
  1030.   DBL dot, k, ki, index, x, y, l, angle, fade, f;
  1031.   VECTOR Temp;
  1032.   COLOUR Cr, Ct;
  1033.   RAINBOW *Rainbow;
  1034.  
  1035.   /* Why are we here. */
  1036.  
  1037.   if (Frame.Rainbow == NULL)
  1038.   {
  1039.     return;
  1040.   }
  1041.  
  1042.   Make_ColourA(Ct, 0.0, 0.0, 0.0, 1.0, 1.0);
  1043.  
  1044.   n = 0;
  1045.  
  1046.   for (Rainbow = Frame.Rainbow; Rainbow != NULL; Rainbow = Rainbow->Next)
  1047.   {
  1048.     if ((Rainbow->Pigment != NULL) && (Rainbow->Distance != 0.0) && (Rainbow->Width != 0.0))
  1049.     {
  1050.       /* Get angle between ray direction and rainbow's up vector. */
  1051.  
  1052.       VDot(x, Ray->Direction, Rainbow->Right_Vector);
  1053.       VDot(y, Ray->Direction, Rainbow->Up_Vector);
  1054.  
  1055.       l = Sqr(x) + Sqr(y);
  1056.  
  1057.       if (l > 0.0)
  1058.       {
  1059.         l = sqrt(l);
  1060.  
  1061.         y /= l;
  1062.       }
  1063.  
  1064.       angle = fabs(acos(y));
  1065.  
  1066.       if (angle <= Rainbow->Arc_Angle)
  1067.       {
  1068.         /* Get dot product between ray direction and antisolar vector. */
  1069.  
  1070.         VDot(dot, Ray->Direction, Rainbow->Antisolar_Vector);
  1071.  
  1072.         if (dot >= 0.0)
  1073.         {
  1074.           /* Get index ([0;1]) into rainbow's colour map. */
  1075.  
  1076.           index = (acos(dot) - Rainbow->Angle) / Rainbow->Width;
  1077.  
  1078.           /* Jitter index. */
  1079.  
  1080.           if (Rainbow->Jitter > 0.0)
  1081.           {
  1082.             index += (2.0 * FRAND() - 1.0) * Rainbow->Jitter;
  1083.           }
  1084.  
  1085.           if ((index >= 0.0) && (index <= 1.0 - EPSILON))
  1086.           {
  1087.             /* Get colour from rainbow's colour map. */
  1088.  
  1089.             Make_Vector(Temp, index, 0.0, 0.0);
  1090.  
  1091.             Compute_Pigment(Cr, Rainbow->Pigment, Temp);
  1092.  
  1093.             /* Get fading value for falloff. */
  1094.  
  1095.             if ((Rainbow->Falloff_Width > 0.0) && (angle > Rainbow->Falloff_Angle))
  1096.             {
  1097.               fade = (angle - Rainbow->Falloff_Angle) / Rainbow->Falloff_Width;
  1098.  
  1099.               fade = (3.0 - 2.0 * fade) * fade * fade;
  1100.             }
  1101.             else
  1102.             {
  1103.               fade = 0.0;
  1104.             }
  1105.  
  1106.             /* Get attenuation factor due to distance. */
  1107.  
  1108.             k = exp(-Intersection->Depth / Rainbow->Distance);
  1109.  
  1110.             /* Colour's transm value is used as minimum attenuation value. */
  1111.  
  1112.             k = max(k, fade * (1.0 - Cr[TRANSM]) + Cr[TRANSM]);
  1113.  
  1114.             /* Now interpolate the colours. */
  1115.  
  1116.             ki = 1.0 - k;
  1117.  
  1118.             /* Attenuate filter value. */
  1119.  
  1120.             f = Cr[FILTER] * ki;
  1121.  
  1122.             Ct[RED]    += k * Colour[RED]   * ((1.0 - f) + f * Cr[RED])   + ki * Cr[RED];
  1123.             Ct[GREEN]  += k * Colour[GREEN] * ((1.0 - f) + f * Cr[GREEN]) + ki * Cr[GREEN];
  1124.             Ct[BLUE]   += k * Colour[BLUE]  * ((1.0 - f) + f * Cr[BLUE])  + ki * Cr[BLUE];
  1125.             Ct[FILTER] *= k * Cr[FILTER];
  1126.             Ct[TRANSM] *= k * Cr[TRANSM];
  1127.  
  1128.             n++;
  1129.           }
  1130.         }
  1131.       }
  1132.     }
  1133.   }
  1134.  
  1135.   if (n > 0)
  1136.   {
  1137.     VInverseScale(Colour, Ct, (DBL)n);
  1138.  
  1139.     Colour[FILTER] *= Ct[FILTER];
  1140.     Colour[TRANSM] *= Ct[TRANSM];
  1141.   }
  1142. }
  1143.  
  1144.  
  1145.  
  1146. /*****************************************************************************
  1147. *
  1148. * FUNCTION
  1149. *
  1150. *   do_skysphere
  1151. *
  1152. * INPUT
  1153. *
  1154. *   Ray    - Current ray
  1155. *
  1156. * OUTPUT
  1157. *
  1158. *   Colour - Current color
  1159. *
  1160. * RETURNS
  1161. *
  1162. * AUTHOR
  1163. *
  1164. *   Dieter Bayer
  1165. *
  1166. * DESCRIPTION
  1167. *
  1168. *   Calculate color of the sky.
  1169. *
  1170. *   Use the ray direction as a point on the skysphere. Thus the sky can
  1171. *   easily be colored with all kinds of pigments.
  1172. *
  1173. * CHANGES
  1174. *
  1175. *   Jul 1994 : Creation.
  1176. *
  1177. *   Dec 1994 : Modified to allow layered pigments. [DB]
  1178. *
  1179. *   Jun 1995 : Added code for alpha channel support. [DB]
  1180. *
  1181. ******************************************************************************/
  1182.  
  1183. static void do_skysphere(Ray, Colour)
  1184. RAY *Ray;
  1185. COLOUR Colour;
  1186. {
  1187.   int i;
  1188.   DBL att, trans;
  1189.   COLOUR Col, Col_Temp, Filter;
  1190.   VECTOR P;
  1191.   SKYSPHERE *Skysphere;
  1192.  
  1193.   /* Why are we here. */
  1194.  
  1195.   if (Frame.Skysphere == NULL)
  1196.   {
  1197.     return;
  1198.   }
  1199.  
  1200.   Make_ColourA(Col, 0.0, 0.0, 0.0, 0.0, 0.0);
  1201.  
  1202.   if (((Skysphere = Frame.Skysphere) != NULL) && (Skysphere->Pigments != NULL))
  1203.   {
  1204.     Make_ColourA(Filter, 1.0, 1.0, 1.0, 1.0, 1.0);
  1205.  
  1206.     trans = 1.0;
  1207.  
  1208.     /* Transform point on unit sphere. */
  1209.  
  1210.     if (Skysphere->Trans != NULL)
  1211.     {
  1212.       MInvTransPoint(P, Ray->Direction, Skysphere->Trans);
  1213.     }
  1214.     else
  1215.     {
  1216.       Assign_Vector(P, Ray->Direction);
  1217.     }
  1218.  
  1219.     for (i = Skysphere->Count-1; i >= 0; i--)
  1220.     {
  1221.       /* Compute sky colour from colour map. */
  1222.  
  1223.       Compute_Pigment(Col_Temp, Skysphere->Pigments[i], P);
  1224.  
  1225.       att = trans * (1.0 - Col_Temp[FILTER] - Col_Temp[TRANSM]);
  1226.  
  1227.       VAddScaledEq(Col, att, Col_Temp);
  1228.  
  1229.       Filter[RED]    *= Col_Temp[RED];
  1230.       Filter[GREEN]  *= Col_Temp[GREEN];
  1231.       Filter[BLUE]   *= Col_Temp[BLUE];
  1232.       Filter[FILTER] *= Col_Temp[FILTER];
  1233.       Filter[TRANSM] *= Col_Temp[TRANSM];
  1234.  
  1235.       trans = fabs(Filter[FILTER]) + fabs(Filter[TRANSM]);
  1236.     }
  1237.  
  1238.     Colour[RED]    = Col[RED]    + Colour[RED]   * (Filter[RED]   * Filter[FILTER] + Filter[TRANSM]);
  1239.     Colour[GREEN]  = Col[GREEN]  + Colour[GREEN] * (Filter[GREEN] * Filter[FILTER] + Filter[TRANSM]);
  1240.     Colour[BLUE]   = Col[BLUE]   + Colour[BLUE]  * (Filter[BLUE]  * Filter[FILTER] + Filter[TRANSM]);
  1241.     Colour[FILTER] = Colour[FILTER] * Filter[FILTER];
  1242.     Colour[TRANSM] = Colour[TRANSM] * Filter[TRANSM];
  1243.   }
  1244. }
  1245.  
  1246.  
  1247.  
  1248. /*****************************************************************************
  1249. *
  1250. * FUNCTION
  1251. *
  1252. *   constant_fog
  1253. *
  1254. * INPUT
  1255. *
  1256. *   Ray    - current ray
  1257. *   Depth  - intersection depth with fog's boundary
  1258. *   Width  - width of the fog along the ray
  1259. *   Fog    - current fog
  1260. *
  1261. * OUTPUT
  1262. *
  1263. *   Colour - color of the fog
  1264. *
  1265. * RETURNS
  1266. *
  1267. * AUTHOR
  1268. *
  1269. *   POV-Ray Team
  1270. *
  1271. * DESCRIPTION
  1272. *
  1273. *   Apply distance attenuated fog.
  1274. *
  1275. * CHANGES
  1276. *
  1277. *   Dec 1994 : Modified to work with multiple fogs. [DB]
  1278. *
  1279. ******************************************************************************/
  1280.  
  1281. static DBL constant_fog(Ray, Depth, Width, Fog, Colour)
  1282. RAY *Ray;
  1283. DBL Depth, Width;
  1284. FOG *Fog;
  1285. COLOUR Colour;
  1286. {
  1287.   DBL k;
  1288.   VECTOR P;
  1289.  
  1290.   if (Fog->Turb != NULL)
  1291.   {
  1292.  
  1293.     Depth += Width / 2.0;
  1294.     
  1295.     VEvaluateRay(P, Ray->Initial, Depth, Ray->Direction);
  1296.  
  1297.     VEvaluateEq(P, Fog->Turb->Turbulence);
  1298.  
  1299.     /* The further away the less influence turbulence has. */
  1300.  
  1301.     k = exp(-Width / Fog->Distance);
  1302.  
  1303.     Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb)*Fog->Turb_Depth);
  1304.   }
  1305.  
  1306.   Assign_Colour(Colour, Fog->Colour);
  1307.  
  1308.   return (exp(-Width / Fog->Distance));
  1309. }
  1310.  
  1311.  
  1312.  
  1313. /*****************************************************************************
  1314. *
  1315. * FUNCTION
  1316. *
  1317. *   ground_fog
  1318. *
  1319. * INPUT
  1320. *
  1321. *   Ray   - current ray
  1322. *   Depth - intersection depth with fog's boundary
  1323. *   Width - width of the fog along the ray
  1324. *   Fog   - current fog
  1325. *
  1326. * OUTPUT
  1327. *
  1328. *   Colour - color of the fog
  1329. *
  1330. * RETURNS
  1331. *
  1332. * AUTHOR
  1333. *
  1334. *   Eric Barish
  1335. *
  1336. * DESCRIPTION
  1337. *
  1338. *   Here is an ascii graph of the ground fog density, it has a maximum
  1339. *   density of 1.0 at Y <= 0, and approaches 0.0 as Y goes up:
  1340. *
  1341. *   ***********************************
  1342. *        |           |            |    ****
  1343. *        |           |            |        ***
  1344. *        |           |            |           ***
  1345. *        |           |            |            | ****
  1346. *        |           |            |            |     *****
  1347. *        |           |            |            |          *******
  1348. *   -----+-----------+------------+------------+-----------+-----
  1349. *       Y=-2        Y=-1         Y=0          Y=1         Y=2
  1350. *
  1351. *   ground fog density is 1 / (Y*Y+1) for Y >= 0 and equals 1.0 for Y <= 0.
  1352. *   (It behaves like regular fog for Y <= 0.)
  1353. *
  1354. *   The integral of the density is atan(Y) (for Y >= 0).
  1355. *
  1356. * CHANGES
  1357. *
  1358. *   Feb 1996 : Changed to behave like normal fog for Y <= 0.
  1359. *              Fixed bug with reversed offset effect. [DB]
  1360. *
  1361. ******************************************************************************/
  1362.  
  1363. static DBL ground_fog(Ray, Depth, Width, Fog, Colour)
  1364. RAY *Ray;
  1365. DBL Depth, Width;
  1366. FOG *Fog;
  1367. COLOUR Colour;
  1368. {
  1369.   DBL fog_density, delta;
  1370.   DBL start, end;
  1371.   DBL y1, y2, k;
  1372.   DBL rdiv;
  1373.   VECTOR P, P1, P2;
  1374.  
  1375.   /* Get start point. */
  1376.  
  1377.   VEvaluateRay(P1, Ray->Initial, Depth, Ray->Direction);
  1378.  
  1379.   /* Get end point. */
  1380.  
  1381.   VLinComb2(P2, 1.0, P1, Width, Ray->Direction);
  1382.  
  1383.   /*
  1384.    * Could preform transfomation here to translate Start and End
  1385.    * points into ground fog space.
  1386.    */
  1387.  
  1388.   VDot(y1, P1, Fog->Up);
  1389.   VDot(y2, P2, Fog->Up);
  1390.  
  1391.   rdiv = (1.0 / Fog->Alt);
  1392.   start = (y1 - Fog->Offset) * rdiv;
  1393.   end   = (y2 - Fog->Offset) * rdiv;
  1394.  
  1395. /*
  1396.   start = (y1 - Fog->Offset) / Fog->Alt;
  1397.   end   = (y2 - Fog->Offset) / Fog->Alt;
  1398. */
  1399.  
  1400.   /* Get integral along y-axis from start to end. */
  1401.  
  1402.   if (start <= 0.0)
  1403.   {
  1404.     if (end <= 0.0)
  1405.     {
  1406.       fog_density = 1.0;
  1407.     }
  1408.     else
  1409.     {
  1410.       fog_density = (atan(end) - start) / (end - start);
  1411.     }
  1412.   }
  1413.   else
  1414.   {
  1415.     if (end <= 0.0)
  1416.     {
  1417.       fog_density = (atan(start) - end) / (start - end);
  1418.     }
  1419.     else
  1420.     {
  1421.       delta = start - end;
  1422.  
  1423.       if (fabs(delta) > EPSILON)
  1424.       {
  1425.         fog_density = (atan(start) - atan(end)) / delta;
  1426.       }
  1427.       else
  1428.       {
  1429.         fog_density = 1.0 / (Sqr(start) + 1.0);
  1430.       }
  1431.     }
  1432.   }
  1433.  
  1434.   /* Apply turbulence. */
  1435.  
  1436.   if (Fog->Turb != NULL)
  1437.   {
  1438.     VHalf(P, P1, P2);
  1439.  
  1440.     VEvaluateEq(P, Fog->Turb->Turbulence);
  1441.  
  1442.     /* The further away the less influence turbulence has. */
  1443.  
  1444.     k = exp(-Width / Fog->Distance);
  1445.  
  1446.     Width *= 1.0 - k * min(1.0, Turbulence(P, Fog->Turb)*Fog->Turb_Depth);
  1447.   }
  1448.  
  1449.   Assign_Colour(Colour, Fog->Colour);
  1450.  
  1451.   return (exp(-Width * fog_density / Fog->Distance));
  1452. }
  1453.  
  1454.  
  1455.  
  1456. /*****************************************************************************
  1457. *
  1458. * FUNCTION
  1459. *
  1460. *   intersect_spotlight
  1461. *
  1462. * INPUT
  1463. *
  1464. *   Ray    - current ray
  1465. *   Light  - current light source
  1466. *
  1467. * OUTPUT
  1468. *
  1469. *   d1, d2 - intersection depths
  1470. *
  1471. * RETURNS
  1472. *
  1473. *   int - TRUE, if hit
  1474. *
  1475. * AUTHOR
  1476. *
  1477. *   Dieter Bayer
  1478. *
  1479. * DESCRIPTION
  1480. *
  1481. *   Intersect a ray with the light cone of a spotlight.
  1482. *
  1483. * CHANGES
  1484. *
  1485. *   Nov 1994 : Creation.
  1486. *
  1487. ******************************************************************************/
  1488.  
  1489. static int intersect_spotlight(Ray, Light, d1, d2)
  1490. RAY *Ray;
  1491. LIGHT_SOURCE *Light;
  1492. DBL *d1, *d2;
  1493. {
  1494.   int viewpoint_is_in_cone;
  1495.   DBL a, b, c, d, m, l, l1, l2, t, t1, t2, k1, k2, k3, k4;
  1496.   DBL rdiv;
  1497.   VECTOR V1;
  1498.  
  1499.   /* Get cone's slope. Note that cos(falloff) is stored in Falloff! */
  1500.  
  1501.   a = acos(Light->Falloff);
  1502.  
  1503.   /* This only works for a < 180 degrees! */
  1504.  
  1505.   m = tan(a);
  1506.  
  1507.   m = 1.0 + Sqr(m);
  1508.  
  1509.   VSub(V1, Ray->Initial, Light->Center);
  1510.  
  1511.   VDot(k1, Ray->Direction, Light->Direction);
  1512.  
  1513.   VDot(k2, V1, Light->Direction);
  1514.  
  1515.   VLength(l, V1);
  1516.  
  1517.   if (l > EPSILON)
  1518.   {
  1519.     viewpoint_is_in_cone = (k2 / l >= Light->Falloff);
  1520.   }
  1521.   else
  1522.   {
  1523.     viewpoint_is_in_cone = FALSE;
  1524.   }
  1525.  
  1526.   if ((k1 <= 0.0) && (k2 < 0.0))
  1527.   {
  1528.     return (FALSE);
  1529.   }
  1530.  
  1531.   VDot(k3, V1, Ray->Direction);
  1532.  
  1533.   VDot(k4, V1, V1);
  1534.  
  1535.   a = 1.0 - Sqr(k1) * m;
  1536.  
  1537.   b = k3 - k1 * k2 * m;
  1538.  
  1539.   c = k4 - Sqr(k2) * m;
  1540.  
  1541.   if (a != 0.0)
  1542.   {
  1543.     d = Sqr(b) - a * c;
  1544.  
  1545.     if (d > EPSILON)
  1546.     {
  1547.       d = sqrt(d);
  1548.  
  1549. /*
  1550.       t1 = (-b + d) / a;
  1551.       t2 = (-b - d) / a;
  1552. */
  1553.       rdiv = (1.0 / a);
  1554.       t1 = (-b + d) * rdiv;
  1555.       t2 = (-b - d) * rdiv;
  1556.  
  1557.       if (t1 > t2)
  1558.       {
  1559.         t = t1; t1 = t2; t2 = t;
  1560.       }
  1561.  
  1562.       l1 = k2 + t1 * k1;
  1563.       l2 = k2 + t2 * k1;
  1564.  
  1565.       if ((l1 <= 0.0) && (l2 <= 0.0))
  1566.       {
  1567.         return (FALSE);
  1568.       }
  1569.  
  1570.       if ((l1 <= 0.0) || (l2 <= 0.0))
  1571.       {
  1572.         if (l1 <= 0.0)
  1573.         {
  1574.           if (viewpoint_is_in_cone)
  1575.           {
  1576.             t1 = 0.0;
  1577.             t2 = (t2 > 0.0) ? (t2) : (Max_Distance);
  1578.           }
  1579.           else
  1580.           {
  1581.             t1 = t2;
  1582.             t2 = Max_Distance;
  1583.           }
  1584.         }
  1585.         else
  1586.         {
  1587.           if (viewpoint_is_in_cone)
  1588.           {
  1589.             t2 = t1;
  1590.             t1 = 0.0;
  1591.           }
  1592.           else
  1593.           {
  1594.             t2 = Max_Distance;
  1595.           }
  1596.         }
  1597.       }
  1598.  
  1599.       *d1 = t1;
  1600.       *d2 = t2;
  1601.  
  1602.       return (TRUE);
  1603.     }
  1604.     else
  1605.     {
  1606.       if (d > -EPSILON)
  1607.       {
  1608.         if (viewpoint_is_in_cone)
  1609.         {
  1610.           *d1 = 0.0;
  1611.           *d2 = -b / a;
  1612.         }
  1613.         else
  1614.         {
  1615.           *d1 = -b / a;
  1616.           *d2 = Max_Distance;
  1617.         }
  1618.  
  1619.         return(TRUE);
  1620.       }
  1621.     }
  1622.   }
  1623.   else
  1624.   {
  1625.     if (viewpoint_is_in_cone)
  1626.     {
  1627.       *d1 = 0.0;
  1628.       *d2 = -c/b;
  1629.  
  1630.       return(TRUE);
  1631.     }
  1632.   }
  1633.  
  1634.   return (FALSE);
  1635. }
  1636.  
  1637.  
  1638.  
  1639. /*****************************************************************************
  1640. *
  1641. * FUNCTION
  1642. *
  1643. *   intersect_cylinderlight
  1644. *
  1645. * INPUT
  1646. *
  1647. *   Ray    - current ray
  1648. *   Light  - current light source
  1649. *
  1650. * OUTPUT
  1651. *
  1652. *   d1, d2 - intersection depths
  1653. *
  1654. * RETURNS
  1655. *
  1656. *   int - TRUE, if hit
  1657. *
  1658. * AUTHOR
  1659. *
  1660. *   Dieter Bayer
  1661. *
  1662. * DESCRIPTION
  1663. *
  1664. *   Intersect a ray with the light cylinder of a cylinderlight.
  1665. *
  1666. * CHANGES
  1667. *
  1668. *   Jan 1995 : Creation.
  1669. *
  1670. ******************************************************************************/
  1671.  
  1672. static int intersect_cylinderlight(Ray, Light, d1, d2)
  1673. RAY *Ray;
  1674. LIGHT_SOURCE *Light;
  1675. DBL *d1, *d2;
  1676. {
  1677.   DBL a, b, c, d, l1, l2, t, t1, t2, k1, k2, k3, k4;
  1678.   DBL rdiv;
  1679.   VECTOR V1;
  1680.  
  1681.   VSub(V1, Ray->Initial, Light->Center);
  1682.  
  1683.   VDot(k1, Ray->Direction, Light->Direction);
  1684.  
  1685.   VDot(k2, V1, Light->Direction);
  1686.  
  1687.   if ((k1 <= 0.0) && (k2 < 0.0))
  1688.   {
  1689.     return (FALSE);
  1690.   }
  1691.  
  1692.   a = 1.0 - Sqr(k1);
  1693.  
  1694.   if (a != 0.0)
  1695.   {
  1696.     VDot(k3, V1, Ray->Direction);
  1697.  
  1698.     VDot(k4, V1, V1);
  1699.  
  1700.     b = k3 - k1 * k2;
  1701.  
  1702.     c = k4 - Sqr(k2) - Sqr(Light->Falloff);
  1703.  
  1704.     d = Sqr(b) - a * c;
  1705.  
  1706.     if (d > EPSILON)
  1707.     {
  1708.       d = sqrt(d);
  1709.  
  1710.       rdiv = (1.0 / a);
  1711.       t1 = (-b + d) * rdiv;
  1712.       t2 = (-b - d) * rdiv;
  1713. /*
  1714.       t1 = (-b + d) / a;
  1715.       t2 = (-b - d) / a;
  1716. */
  1717.       if (t1 > t2)
  1718.       {
  1719.         t = t1; t1 = t2; t2 = t;
  1720.       }
  1721.  
  1722.       l1 = k2 + t1 * k1;
  1723.       l2 = k2 + t2 * k1;
  1724.  
  1725.       if ((l1 <= 0.0) && (l2 <= 0.0))
  1726.       {
  1727.         return (FALSE);
  1728.       }
  1729.  
  1730.       if ((l1 <= 0.0) || (l2 <= 0.0))
  1731.       {
  1732.         if (l1 <= 0.0)
  1733.         {
  1734.           t1 = 0.0;
  1735.         }
  1736.         else
  1737.         {
  1738.           t2 = (Max_Distance - k2) / k1;
  1739.         }
  1740.       }
  1741.  
  1742.       *d1 = t1;
  1743.       *d2 = t2;
  1744.  
  1745.       return (TRUE);
  1746.     }
  1747.   }
  1748.  
  1749.   return (FALSE);
  1750. }
  1751.  
  1752.  
  1753.  
  1754. /*****************************************************************************
  1755. *
  1756. * FUNCTION
  1757. *
  1758. *   Create_Atmosphere
  1759. *
  1760. * INPUT
  1761. *
  1762. * OUTPUT
  1763. *
  1764. * RETURNS
  1765. *
  1766. *   ATMOSPHERE * - created atmosphere
  1767. *
  1768. * AUTHOR
  1769. *
  1770. *   Dieter Bayer
  1771. *
  1772. * DESCRIPTION
  1773. *
  1774. *   Create an atmosphere.
  1775. *
  1776. * CHANGES
  1777. *
  1778. *   Dec 1994 : Creation.
  1779. *
  1780. ******************************************************************************/
  1781.  
  1782. ATMOSPHERE *Create_Atmosphere()
  1783. {
  1784.   ATMOSPHERE *New;
  1785.  
  1786.   New = (ATMOSPHERE *)POV_MALLOC(sizeof(ATMOSPHERE), "fog");
  1787.  
  1788.   New->Type = ISOTROPIC_SCATTERING;
  1789.  
  1790.   New->Samples            = 100;
  1791.   New->Distance           = 0.0;
  1792.   New->Distance_Threshold = 0.005;
  1793.   New->Scattering         = 1.0;
  1794.   New->Eccentricity       = 0.0;
  1795.  
  1796.   Make_Colour(New->Colour, 0.0, 0.0, 0.0);
  1797.  
  1798.   New->AA_Level     = 0;
  1799.   New->AA_Threshold = 0.3;
  1800.   New->Jitter       = 0.0;
  1801.  
  1802.   return (New);
  1803. }
  1804.  
  1805.  
  1806.  
  1807. /*****************************************************************************
  1808. *
  1809. * FUNCTION
  1810. *
  1811. *   Copy_Atmosphere
  1812. *
  1813. * INPUT
  1814. *
  1815. *   Old - atmosphere to copy
  1816. *
  1817. * OUTPUT
  1818. *
  1819. * RETURNS
  1820. *
  1821. *   ATMOSPHERE * - new atmosphere
  1822. *
  1823. * AUTHOR
  1824. *
  1825. *   Dieter Bayer
  1826. *
  1827. * DESCRIPTION
  1828. *
  1829. *   Copy an atmosphere.
  1830. *
  1831. * CHANGES
  1832. *
  1833. *   Dec 1994 : Creation.
  1834. *
  1835. ******************************************************************************/
  1836.  
  1837. void *Copy_Atmosphere(Old)
  1838. ATMOSPHERE *Old;
  1839. {
  1840.   ATMOSPHERE *New;
  1841.  
  1842.   New = Create_Atmosphere();
  1843.  
  1844.   *New = *Old;
  1845.  
  1846.   return (New);
  1847. }
  1848.  
  1849.  
  1850.  
  1851. /*****************************************************************************
  1852. *
  1853. * FUNCTION
  1854. *
  1855. *   Destroy_Atmosphere
  1856. *
  1857. * INPUT
  1858. *
  1859. *   Atmosphere - atmosphere to destroy
  1860. *
  1861. * OUTPUT
  1862. *
  1863. * RETURNS
  1864. *
  1865. * AUTHOR
  1866. *
  1867. *   Dieter Bayer
  1868. *
  1869. * DESCRIPTION
  1870. *
  1871. *   Destroy an atmosphere.
  1872. *
  1873. * CHANGES
  1874. *
  1875. *   Dec 1994 : Creation.
  1876. *
  1877. ******************************************************************************/
  1878.  
  1879. void Destroy_Atmosphere(Atmosphere)
  1880. ATMOSPHERE *Atmosphere;
  1881. {
  1882.   if (Atmosphere != NULL)
  1883.   {
  1884.     POV_FREE(Atmosphere);
  1885.   }
  1886. }
  1887.  
  1888.  
  1889.  
  1890. /*****************************************************************************
  1891. *
  1892. * FUNCTION
  1893. *
  1894. *   Create_Fog
  1895. *
  1896. * INPUT
  1897. *
  1898. * OUTPUT
  1899. *
  1900. * RETURNS
  1901. *
  1902. *   FOG * - created fog
  1903. *
  1904. * AUTHOR
  1905. *
  1906. *   Dieter Bayer
  1907. *
  1908. * DESCRIPTION
  1909. *
  1910. *   Create a fog.
  1911. *
  1912. * CHANGES
  1913. *
  1914. *   Dec 1994 : Creation.
  1915. *
  1916. ******************************************************************************/
  1917.  
  1918. FOG *Create_Fog()
  1919. {
  1920.   FOG *New;
  1921.  
  1922.   New = (FOG *)POV_MALLOC(sizeof(FOG), "fog");
  1923.  
  1924.   New->Type = ORIG_FOG;
  1925.  
  1926.   New->Distance = 0.0;
  1927.   New->Alt      = 0.0;
  1928.   New->Offset   = 0.0;
  1929.  
  1930.   Make_ColourA(New->Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  1931.  
  1932.   Make_Vector(New->Up, 0.0, 1.0, 0.0);
  1933.  
  1934.   New->Turb = NULL;
  1935.   New->Turb_Depth = 0.5;
  1936.  
  1937.   New->Next = NULL;
  1938.  
  1939.   return (New);
  1940. }
  1941.  
  1942.  
  1943.  
  1944. /*****************************************************************************
  1945. *
  1946. * FUNCTION
  1947. *
  1948. *   Copy_Fog
  1949. *
  1950. * INPUT
  1951. *
  1952. *   Old - fog to copy
  1953. *
  1954. * OUTPUT
  1955. *
  1956. * RETURNS
  1957. *
  1958. *   FOG * - new fog
  1959. *
  1960. * AUTHOR
  1961. *
  1962. *   Dieter Bayer
  1963. *
  1964. * DESCRIPTION
  1965. *
  1966. *   Copy a fog.
  1967. *
  1968. * CHANGES
  1969. *
  1970. *   Dec 1994 : Creation.
  1971. *
  1972. ******************************************************************************/
  1973.  
  1974. void *Copy_Fog(Old)
  1975. FOG *Old;
  1976. {
  1977.   FOG *New;
  1978.  
  1979.   New = Create_Fog();
  1980.  
  1981.   *New = *Old;
  1982.  
  1983.   New->Turb = (TURB *)Copy_Warps(((WARP *)Old->Turb));
  1984.  
  1985.   return (New);
  1986. }
  1987.  
  1988.  
  1989.  
  1990. /*****************************************************************************
  1991. *
  1992. * FUNCTION
  1993. *
  1994. *   Destroy_Fog
  1995. *
  1996. * INPUT
  1997. *
  1998. *   Fog - fog to destroy
  1999. *
  2000. * OUTPUT
  2001. *
  2002. * RETURNS
  2003. *
  2004. * AUTHOR
  2005. *
  2006. *   Dieter Bayer
  2007. *
  2008. * DESCRIPTION
  2009. *
  2010. *   Destroy a fog.
  2011. *
  2012. * CHANGES
  2013. *
  2014. *   Dec 1994 : Creation.
  2015. *
  2016. ******************************************************************************/
  2017.  
  2018. void Destroy_Fog(Fog)
  2019. FOG *Fog;
  2020. {
  2021.   if (Fog != NULL)
  2022.   {
  2023.     Destroy_Turb(Fog->Turb);
  2024.  
  2025.     POV_FREE(Fog);
  2026.   }
  2027. }
  2028.  
  2029.  
  2030.  
  2031. /*****************************************************************************
  2032. *
  2033. * FUNCTION
  2034. *
  2035. *   Create_Rainbow
  2036. *
  2037. * INPUT
  2038. *
  2039. * OUTPUT
  2040. *
  2041. * RETURNS
  2042. *
  2043. *   RAINBOW * - created rainbow
  2044. *
  2045. * AUTHOR
  2046. *
  2047. *   Dieter Bayer
  2048. *
  2049. * DESCRIPTION
  2050. *
  2051. *   Create a rainbow.
  2052. *
  2053. * CHANGES
  2054. *
  2055. *   Dec 1994 : Creation.
  2056. *
  2057. ******************************************************************************/
  2058.  
  2059. RAINBOW *Create_Rainbow()
  2060. {
  2061.   RAINBOW *New;
  2062.  
  2063.   New = (RAINBOW *)POV_MALLOC(sizeof(RAINBOW), "fog");
  2064.  
  2065.   New->Distance = Max_Distance;
  2066.   New->Jitter   = 0.0;
  2067.   New->Angle    = 0.0;
  2068.   New->Width    = 0.0;
  2069.  
  2070.   New->Falloff_Width  = 0.0;
  2071.   New->Arc_Angle      = 180.0;
  2072.   New->Falloff_Angle  = 180.0;
  2073.  
  2074.   New->Pigment = NULL;
  2075.  
  2076.   Make_Vector(New->Antisolar_Vector, 0.0, 0.0, 0.0);
  2077.  
  2078.   Make_Vector(New->Right_Vector, 1.0, 0.0, 0.0);
  2079.   Make_Vector(New->Up_Vector, 0.0, 1.0, 0.0);
  2080.  
  2081.   New->Next = NULL;
  2082.  
  2083.   return (New);
  2084. }
  2085.  
  2086.  
  2087.  
  2088. /*****************************************************************************
  2089. *
  2090. * FUNCTION
  2091. *
  2092. *   Copy_Rainbow
  2093. *
  2094. * INPUT
  2095. *
  2096. *   Old - rainbow to copy
  2097. *
  2098. * OUTPUT
  2099. *
  2100. * RETURNS
  2101. *
  2102. *   RAINBOW * - new rainbow
  2103. *
  2104. * AUTHOR
  2105. *
  2106. *   Dieter Bayer
  2107. *
  2108. * DESCRIPTION
  2109. *
  2110. *   Copy a rainbow.
  2111. *
  2112. * CHANGES
  2113. *
  2114. *   Dec 1994 : Creation.
  2115. *
  2116. ******************************************************************************/
  2117.  
  2118. void *Copy_Rainbow(Old)
  2119. RAINBOW *Old;
  2120. {
  2121.   RAINBOW *New;
  2122.  
  2123.   New = Create_Rainbow();
  2124.  
  2125.   *New = *Old;
  2126.  
  2127.   return (New);
  2128. }
  2129.  
  2130.  
  2131.  
  2132. /*****************************************************************************
  2133. *
  2134. * FUNCTION
  2135. *
  2136. *   Destroy_Rainbow
  2137. *
  2138. * INPUT
  2139. *
  2140. *   Rainbow - rainbow to destroy
  2141. *
  2142. * OUTPUT
  2143. *
  2144. * RETURNS
  2145. *
  2146. * AUTHOR
  2147. *
  2148. *   Dieter Bayer
  2149. *
  2150. * DESCRIPTION
  2151. *
  2152. *   Destroy a rainbow.
  2153. *
  2154. * CHANGES
  2155. *
  2156. *   Dec 1994 : Creation.
  2157. *
  2158. ******************************************************************************/
  2159.  
  2160. void Destroy_Rainbow(Rainbow)
  2161. RAINBOW *Rainbow;
  2162. {
  2163.   if (Rainbow != NULL)
  2164.   {
  2165.     Destroy_Pigment(Rainbow->Pigment);
  2166.  
  2167.     POV_FREE(Rainbow);
  2168.   }
  2169. }
  2170.  
  2171.  
  2172.  
  2173. /*****************************************************************************
  2174. *
  2175. * FUNCTION
  2176. *
  2177. *   Create_Skysphere
  2178. *
  2179. * INPUT
  2180. *
  2181. * OUTPUT
  2182. *
  2183. * RETURNS
  2184. *
  2185. *   SKYSPHERE * - created skysphere
  2186. *
  2187. * AUTHOR
  2188. *
  2189. *   Dieter Bayer
  2190. *
  2191. * DESCRIPTION
  2192. *
  2193. *   Create a skysphere.
  2194. *
  2195. * CHANGES
  2196. *
  2197. *   Dec 1994 : Creation.
  2198. *
  2199. ******************************************************************************/
  2200.  
  2201. SKYSPHERE *Create_Skysphere()
  2202. {
  2203.   SKYSPHERE *New;
  2204.  
  2205.   New = (SKYSPHERE *)POV_MALLOC(sizeof(SKYSPHERE), "fog");
  2206.  
  2207.   New->Count = 0;
  2208.  
  2209.   New->Pigments = NULL;
  2210.  
  2211.   New->Trans = Create_Transform();
  2212.  
  2213.   return (New);
  2214. }
  2215.  
  2216.  
  2217.  
  2218. /*****************************************************************************
  2219. *
  2220. * FUNCTION
  2221. *
  2222. *   Copy_Skysphere
  2223. *
  2224. * INPUT
  2225. *
  2226. *   Old - skysphere to copy
  2227. *
  2228. * OUTPUT
  2229. *
  2230. * RETURNS
  2231. *
  2232. *   SKYSPHERE * - copied skysphere
  2233. *
  2234. * AUTHOR
  2235. *
  2236. *   Dieter Bayer
  2237. *
  2238. * DESCRIPTION
  2239. *
  2240. *   Copy a skysphere.
  2241. *
  2242. * CHANGES
  2243. *
  2244. *   Dec 1994 : Creation.
  2245. *
  2246. ******************************************************************************/
  2247.  
  2248. void *Copy_Skysphere(Old)
  2249. SKYSPHERE *Old;
  2250. {
  2251.   int i;
  2252.   SKYSPHERE *New;
  2253.  
  2254.   New = Create_Skysphere();
  2255.  
  2256.   Destroy_Transform(New->Trans);
  2257.  
  2258.   *New = *Old;
  2259.  
  2260.   New->Trans = Copy_Transform(Old->Trans);
  2261.  
  2262.   if (New->Count > 0)
  2263.   {
  2264.     New->Pigments = (PIGMENT **)POV_MALLOC(New->Count*sizeof(PIGMENT *), "skysphere pigment");
  2265.  
  2266.     for (i = 0; i < New->Count; i++)
  2267.     {
  2268.       New->Pigments[i] = Copy_Pigment(Old->Pigments[i]);
  2269.     }
  2270.   }
  2271.  
  2272.   return (New);
  2273. }
  2274.  
  2275.  
  2276.  
  2277. /*****************************************************************************
  2278. *
  2279. * FUNCTION
  2280. *
  2281. *   Destroy_Skysphere
  2282. *
  2283. * INPUT
  2284. *
  2285. *   Skysphere - skysphere to destroy
  2286. *
  2287. * OUTPUT
  2288. *
  2289. * RETURNS
  2290. *
  2291. * AUTHOR
  2292. *
  2293. *   Dieter Bayer
  2294. *
  2295. * DESCRIPTION
  2296. *
  2297. *   Destroy a skysphere.
  2298. *
  2299. * CHANGES
  2300. *
  2301. *   Dec 1994 : Creation.
  2302. *
  2303. ******************************************************************************/
  2304.  
  2305. void Destroy_Skysphere(Skysphere)
  2306. SKYSPHERE *Skysphere;
  2307. {
  2308.   int i;
  2309.  
  2310.   if (Skysphere != NULL)
  2311.   {
  2312.     for (i = 0; i < Skysphere->Count; i++)
  2313.     {
  2314.       Destroy_Pigment(Skysphere->Pigments[i]);
  2315.     }
  2316.  
  2317.     POV_FREE(Skysphere->Pigments);
  2318.  
  2319.     Destroy_Transform(Skysphere->Trans);
  2320.  
  2321.     POV_FREE(Skysphere);
  2322.   }
  2323. }
  2324.  
  2325.  
  2326.  
  2327. /*****************************************************************************
  2328. *
  2329. * FUNCTION
  2330. *
  2331. *   Rotate_Skysphere
  2332. *
  2333. * INPUT
  2334. *
  2335. *   Vector - Rotation vector
  2336. *
  2337. * OUTPUT
  2338. *
  2339. *   Skysphere - Pointer to skysphere structure
  2340. *
  2341. * RETURNS
  2342. *
  2343. * AUTHOR
  2344. *
  2345. *   Dieter Bayer
  2346. *
  2347. * DESCRIPTION
  2348. *
  2349. *   Rotate a skysphere.
  2350. *
  2351. * CHANGES
  2352. *
  2353. *   Feb 1996 : Creation.
  2354. *
  2355. ******************************************************************************/
  2356.  
  2357. void Rotate_Skysphere(Skysphere, Vector)
  2358. SKYSPHERE *Skysphere;
  2359. VECTOR Vector;
  2360. {
  2361.   TRANSFORM Trans;
  2362.  
  2363.   Compute_Rotation_Transform(&Trans, Vector);
  2364.  
  2365.   Transform_Skysphere(Skysphere, &Trans);
  2366. }
  2367.  
  2368.  
  2369.  
  2370. /*****************************************************************************
  2371. *
  2372. * FUNCTION
  2373. *
  2374. *   Scale_Skysphere
  2375. *
  2376. * INPUT
  2377. *
  2378. *   Vector - Scaling vector
  2379. *
  2380. * OUTPUT
  2381. *
  2382. *   Skysphere - Pointer to skysphere structure
  2383. *
  2384. * RETURNS
  2385. *
  2386. * AUTHOR
  2387. *
  2388. *   Dieter Bayer
  2389. *
  2390. * DESCRIPTION
  2391. *
  2392. *   Scale a skysphere.
  2393. *
  2394. * CHANGES
  2395. *
  2396. *   Feb 1996 : Creation.
  2397. *
  2398. ******************************************************************************/
  2399.  
  2400. void Scale_Skysphere(Skysphere, Vector)
  2401. SKYSPHERE *Skysphere;
  2402. VECTOR Vector;
  2403. {
  2404.   TRANSFORM Trans;
  2405.  
  2406.   Compute_Scaling_Transform(&Trans, Vector);
  2407.  
  2408.   Transform_Skysphere(Skysphere, &Trans);
  2409. }
  2410.  
  2411.  
  2412.  
  2413. /*****************************************************************************
  2414. *
  2415. * FUNCTION
  2416. *
  2417. *   Translate_Skysphere
  2418. *
  2419. * INPUT
  2420. *
  2421. *   Vector - Translation vector
  2422. *
  2423. * OUTPUT
  2424. *
  2425. *   Skysphere - Pointer to skysphere structure
  2426. *
  2427. * RETURNS
  2428. *
  2429. * AUTHOR
  2430. *
  2431. *   Dieter Bayer
  2432. *
  2433. * DESCRIPTION
  2434. *
  2435. *   Translate a skysphere.
  2436. *
  2437. * CHANGES
  2438. *
  2439. *   Feb 1996 : Creation.
  2440. *
  2441. ******************************************************************************/
  2442.  
  2443. void Translate_Skysphere(Skysphere, Vector)
  2444. SKYSPHERE *Skysphere;
  2445. VECTOR Vector;
  2446. {
  2447.   TRANSFORM Trans;
  2448.  
  2449.   Compute_Translation_Transform(&Trans, Vector);
  2450.  
  2451.   Transform_Skysphere(Skysphere, &Trans);
  2452. }
  2453.  
  2454.  
  2455.  
  2456. /*****************************************************************************
  2457. *
  2458. * FUNCTION
  2459. *
  2460. *   Transform_Skysphere
  2461. *
  2462. * INPUT
  2463. *
  2464. *   Trans  - Pointer to transformation
  2465. *
  2466. * OUTPUT
  2467. *
  2468. *   Skysphere - Pointer to skysphere structure
  2469. *
  2470. * RETURNS
  2471. *
  2472. * AUTHOR
  2473. *
  2474. *   Dieter Bayer
  2475. *
  2476. * DESCRIPTION
  2477. *
  2478. *   Transform a skysphere.
  2479. *
  2480. * CHANGES
  2481. *
  2482. *   Feb 1996 : Creation.
  2483. *
  2484. ******************************************************************************/
  2485.  
  2486. void Transform_Skysphere(Skysphere, Trans)
  2487. SKYSPHERE *Skysphere;
  2488. TRANSFORM *Trans;
  2489. {
  2490.   if (Skysphere->Trans == NULL)
  2491.   {
  2492.     Skysphere->Trans = Create_Transform();
  2493.   }
  2494.  
  2495.   Compose_Transforms(Skysphere->Trans, Trans);
  2496. }
  2497.  
  2498.  
  2499.  
  2500.